import { DefaultStage } from '../default-stage';
import { ICommunityData } from '../../data/community';
import { CommunityData } from '../community/community-data';
import { Troop } from '../attachment/troop';
import { BASE_ENLIST_RATIO } from '../../data/data';
import { FIXED_BLOC, PLAYER_BLOC } from '../../global/global-constant';


interface IAbstractBlocOptions {
    blocName: PLAYER_BLOC | FIXED_BLOC;
    enlistRatio?: number;

    nuLi?: number;
    pingMin?: number;
    shiDaFu?: number;
    guiZu?: number;

    nongYe?: number;
    muYe?: number;
    gongShang?: number;
    yingZao?: number;

    qingBao?: number;
    zhanShu?: number;
    houQin?: number;
    shiQi?: number;

    zhengTong?: number;
    tongZhi?: number;
    deXing?: number;

    zheXue?: number;
    liYue?: number;
    jiaoYu?: number;
}


class AbstractBloc<T extends IAbstractBlocOptions = IAbstractBlocOptions> {

    public readonly name: PLAYER_BLOC | FIXED_BLOC;
    public readonly stage: DefaultStage;

    protected options: T;
    protected communities: Array<ICommunityData> = [];
    protected troops: Array<Troop> = [];
    protected currentArmy: number = 0;

    public population: number = 0;

    constructor(stage: DefaultStage, options: T) {
        this.options = this.setOptions(options);
        this.name = options.blocName;
        this.stage = stage;
    }

    protected setOptions(options: T): T {
        const ops = options;
        ops.enlistRatio = ops.enlistRatio || BASE_ENLIST_RATIO;
        ops.nuLi = ops.nuLi || 1;
        ops.pingMin = ops.pingMin || 1;
        ops.shiDaFu = ops.shiDaFu || 1;
        ops.guiZu = ops.guiZu || 1;
        ops.nongYe = ops.nongYe || 1;
        ops.muYe = ops.muYe || 1;
        ops.gongShang = ops.gongShang || 1;
        ops.yingZao = ops.yingZao || 1;
        ops.qingBao = ops.qingBao || 1;
        ops.zhanShu = ops.zhanShu || 1;
        ops.houQin = ops.houQin || 1;
        ops.shiQi = ops.shiQi || 1;
        ops.zhengTong = ops.zhengTong || 1;
        ops.tongZhi = ops.tongZhi || 1;
        ops.deXing = ops.deXing || 1;
        ops.zheXue = ops.zheXue || 1;
        ops.liYue = ops.liYue || 1;
        ops.jiaoYu = ops.jiaoYu || 1;
        return ops;
    }

    public updatePopulation(): void {
        this.population = this.communities.reduce((acc, c) => {
            return acc + (c.population || 0);
        }, 0);
    }

    public updateSovereign(): void {
        this.communities.length = 0;
        CommunityData.allData.forEach(c => {
            if (c.sovereign === this.name) this.communities.push(c);
        });
    }

    public set enlistRatio(value: number) { this.options.enlistRatio = value; }

    public get nuLi(): number { return this.options.nuLi!; }
    public set nuLi(value: number) { this.options.nuLi = value; }
    public get pingMin(): number { return this.options.pingMin!; }
    public set pingMin(value: number) { this.options.pingMin = value; }
    public get shiDaFu(): number { return this.options.shiDaFu!; }
    public set shiDaFu(value: number) { this.options.shiDaFu = value; }
    public get guiZu(): number { return this.options.guiZu!; }
    public set guiZu(value: number) { this.options.guiZu = value; }
    public get nongYe(): number { return this.options.nongYe!; }
    public set nongYe(value: number) { this.options.nongYe = value; }
    public get muYe(): number { return this.options.muYe!; }
    public set muYe(value: number) { this.options.muYe = value; }
    public get gongShang(): number { return this.options.gongShang!; }
    public set gongShang(value: number) { this.options.gongShang = value; }
    public get yingZao(): number { return this.options.yingZao!; }
    public set yingZao(value: number) { this.options.yingZao = value; }
    public get qingBao(): number { return this.options.qingBao!; }
    public set qingBao(value: number) { this.options.qingBao = value; }
    public get zhanShu(): number { return this.options.zhanShu!; }
    public set zhanShu(value: number) { this.options.zhanShu = value; }
    public get houQin(): number { return this.options.houQin!; }
    public set houQin(value: number) { this.options.houQin = value; }
    public get shiQi(): number { return this.options.shiQi!; }
    public set shiQi(value: number) { this.options.shiQi = value; }
    public get zhengTong(): number { return this.options.zhengTong!; }
    public set zhengTong(value: number) { this.options.zhengTong = value; }
    public get tongZhi(): number { return this.options.tongZhi!; }
    public set tongZhi(value: number) { this.options.tongZhi = value; }
    public get deXing(): number { return this.options.deXing!; }
    public set deXing(value: number) { this.options.deXing = value; }
    public get zheXue(): number { return this.options.zheXue!; }
    public set zheXue(value: number) { this.options.zheXue = value; }
    public get liYue(): number { return this.options.liYue!; }
    public set liYue(value: number) { this.options.liYue = value; }
    public get jiaoYu(): number { return this.options.jiaoYu!; }
    public set jiaoYu(value: number) { this.options.jiaoYu = value; }

}


export { AbstractBloc };
export type { IAbstractBlocOptions };